gdk/wayland: Ensure to clean up stale touchpoint data on surface destroy
authorCarlos Garnacho <carlosg@gnome.org>
Fri, 24 Apr 2020 21:11:00 +0000 (23:11 +0200)
committerCarlos Garnacho <carlosg@gnome.org>
Fri, 24 Apr 2020 21:11:00 +0000 (23:11 +0200)
If the wl_surface receiving touch events is destroyed, we will get no
wl_touch.up event to remove the touchpoint from our internal accounting.
Check for this, and drop touchpoints happening in surfaces that do
disappear during operation.

gdk/wayland/gdkdevice-wayland.c
gdk/wayland/gdkseat-wayland.h
gdk/wayland/gdksurface-wayland.c

index 075a2a7c36f72ee6deda6ac5624875b72ca03745..b30b1e63c75309a3d4122c9cb42731c380cd5a50 100644 (file)
@@ -2313,6 +2313,22 @@ gdk_wayland_seat_remove_touch (GdkWaylandSeat *seat,
   g_hash_table_remove (seat->touches, GUINT_TO_POINTER (id));
 }
 
+void
+gdk_wayland_seat_clear_touchpoints (GdkWaylandSeat *seat,
+                                    GdkSurface     *surface)
+{
+  GHashTableIter iter;
+  GdkWaylandTouchData *touch;
+
+  g_hash_table_iter_init (&iter, seat->touches);
+
+  while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &touch))
+    {
+      if (touch->surface == surface)
+        g_hash_table_iter_remove (&iter);
+    }
+}
+
 static void
 mimic_pointer_emulating_touch_info (GdkDevice           *device,
                                     GdkWaylandTouchData *touch)
index eccc79281764e134896eab3fde017a130bf990d0..711c597ae95b00c9b7bad8cbe32ebb104208e332 100644 (file)
@@ -43,4 +43,7 @@ GType gdk_wayland_seat_get_type (void) G_GNUC_CONST;
 
 void gdk_wayland_seat_update_cursor_scale (GdkWaylandSeat *seat);
 
+void gdk_wayland_seat_clear_touchpoints (GdkWaylandSeat *seat,
+                                         GdkSurface     *surface);
+
 #endif /* __GDK_WAYLAND_SEAT_H__ */
index c644608031ea8fe05ad06d3d3c3a7e2e075aabd8..2bbc4ef40ff5a9af35eb9c1567706e1aa3730f47 100644 (file)
@@ -2683,6 +2683,14 @@ gdk_wayland_surface_hide_surface (GdkSurface *surface)
 static void
 gdk_wayland_surface_hide (GdkSurface *surface)
 {
+  GdkSeat *seat;
+
+  seat = gdk_display_get_default_seat (surface->display);
+
+  if (surface->autohide)
+    gdk_seat_ungrab (seat);
+
+  gdk_wayland_seat_clear_touchpoints (GDK_WAYLAND_SEAT (seat), surface);
   gdk_wayland_surface_hide_surface (surface);
   _gdk_surface_clear_update_area (surface);
 }